package com.tanhua.server.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.dubbo.config.annotation.Reference;
import com.tanhua.common.pojo.User;
import com.tanhua.common.pojo.UserInfo;
import com.tanhua.common.service.PicUploadService;
import com.tanhua.common.utils.RelativeDateFormat;
import com.tanhua.common.utils.UserThreadLocal;
import com.tanhua.common.vo.PicUploadResult;
import com.tanhua.dubbo.server.api.MomentsApi;
import com.tanhua.dubbo.server.api.VisitorsApi;
import com.tanhua.dubbo.server.pojo.Comment;
import com.tanhua.dubbo.server.pojo.Publish;
import com.tanhua.dubbo.server.pojo.Visitors;
import com.tanhua.dubbo.server.vo.PageInfo;
import com.tanhua.server.vo.CommentVo;
import com.tanhua.server.vo.PageResult;
import com.tanhua.server.vo.QuanZiVo;
import com.tanhua.server.vo.VisitorsVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;

@Service
public class QXMomentsService {

    @Autowired
    private UserService userService;

    @Reference(version = "1.0.0")
    private MomentsApi momentsApi;

    @Reference(version = "1.0.0")
    private VisitorsApi visitorsApi;

    @Autowired
    private UserInfoService userInfoService;

    @Autowired
    private PicUploadService picUploadService;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    private static final String FREEZE_USER_REDIS_KEY_PREFIX = "FREEZE_USER";

    /**
     * 查看好友的动态列表
     *
     * @param page
     * @param pageSize
     * @return
     */
    public PageResult findPublishList(Integer page, Integer pageSize) {
        //创建一个pageResult对象用于封装返回页面的信息,页面需要返回的信息包含了好友的动态信息,以及好友的个人信息,
        //动态信息需要去mongodb中查询,个人信息则需要去MySQL中查询
        PageResult pageResult = new PageResult();
        pageResult.setPage(page);
        pageResult.setPagesize(pageSize);

        //获取User对象，无需对User对象校验，其一定不为null
        User user = UserThreadLocal.get();

        //通过dubbo远程调用获取好友的动态信息
        PageInfo<Publish> publishPageInfo = momentsApi.findPublishList(user.getId(), page, pageSize);
        List<Publish> records = publishPageInfo.getRecords();
        if (CollUtil.isEmpty(records)) {
            return pageResult;
        }
        //创建一个集合用于封装QuanZiVo对象
        List<QuanZiVo> quanZiVoList = new ArrayList<>();
        for (Publish record : records) {
            QuanZiVo quanZiVo = new QuanZiVo();
            quanZiVo.setId(record.getId().toHexString());//发布的动态的ID
            quanZiVo.setTextContent(record.getText());
            quanZiVo.setImageContent(record.getMedias().toArray(new String[]{}));
            quanZiVo.setUserId(record.getUserId());
            quanZiVo.setCreateDate(RelativeDateFormat.format(new Date(record.getCreated())));
            quanZiVoList.add(quanZiVo);
        }
        //查询用户的具体信息
        List<Object> userIds = CollUtil.getFieldValues(records, "userId");
        List<UserInfo> userInfoList = userInfoService.findUserInfoByUserIds(userIds);
        for (QuanZiVo quanZiVo : quanZiVoList) {
            //找到对应的用户信息
            for (UserInfo userInfo : userInfoList) {
                if (userInfo.getUserId().longValue() == quanZiVo.getUserId().longValue()) {
                    fillQuanZiVoByUserInfo(userInfo, quanZiVo);
                    break;
                }
            }
        }
        pageResult.setItems(quanZiVoList);
        return pageResult;
    }

    /**
     * 填充用户信息
     *
     * @param userInfo
     * @param quanZiVo
     */
    private void fillQuanZiVoByUserInfo(UserInfo userInfo, QuanZiVo quanZiVo) {
        BeanUtils.copyProperties(userInfo, quanZiVo, "id");
        quanZiVo.setGender(userInfo.getSex().name().toLowerCase());
        quanZiVo.setTags(userInfo.getTags().split(","));

        quanZiVo.setNickname(userInfo.getNickName());
        quanZiVo.setAvatar(userInfo.getLogo());

        User user = UserThreadLocal.get();

        quanZiVo.setCommentCount(0); //TODO 评论数
        quanZiVo.setDistance("1.2公里"); //TODO 距离
        quanZiVo.setHasLiked(momentsApi.findLikeRecord(user.getId(), quanZiVo.getId()) ? 1 : 0); //是否点赞（1是，0否）
        quanZiVo.setLikeCount(Convert.toInt(momentsApi.findLikeCount(quanZiVo.getId()))); //点赞数
        quanZiVo.setHasLoved(momentsApi.findLoveRecord(user.getId(), quanZiVo.getId()) ? 1 : 0); //是否喜欢（1是，0否）
        quanZiVo.setLoveCount(Convert.toInt(momentsApi.findLoveCount(quanZiVo.getId()))); //喜欢数
    }

    /**
     * 发布动态
     *
     * @param textContent
     * @param location
     * @param latitude
     * @param longitude
     * @param multipartFile
     * @return
     */
    public String savePublish(String textContent,
                              String location,
                              String latitude,
                              String longitude, MultipartFile[] multipartFile) {

        //获取User对象，无需对User对象校验，其一定不为null
        User user = UserThreadLocal.get();

        Publish publish = new Publish();
        publish.setUserId(user.getId());
        publish.setText(textContent);
        publish.setLocationName(location);
        publish.setLatitude(latitude);
        publish.setLongitude(longitude);
        publish.setSeeType(1);
        //设置动态的审核状态默认为3
        publish.setState("3");
        publish.setTopState(1);

        List<String> picUrls = new ArrayList<>();
        //图片上传
        for (MultipartFile file : multipartFile) {
            PicUploadResult picUploadResult = picUploadService.upload(file);
            picUrls.add(picUploadResult.getName());
        }

        publish.setMedias(picUrls);
        return momentsApi.savePublish(publish);
    }

    /**
     * 查询推荐用户动态信息的服务
     *
     * @param page
     * @param pageSize
     * @return
     */
    public PageResult findRecommendPublish(Integer page, Integer pageSize) {
        //分析：通过dubbo中的服务查询系统推荐动态
        //通过mysql查询用户的信息，回写到结果对象中（QuanZiVo）
        PageResult pageResult = new PageResult();
        pageResult.setPage(page);
        pageResult.setPagesize(pageSize);

        User user = UserThreadLocal.get();

        PageInfo<Publish> recommendPublishList = momentsApi.findRecommendPublishList(user.getId(), page, pageSize);
        List<Publish> records = recommendPublishList.getRecords();
        if (CollUtil.isEmpty(records)) {
            return pageResult;
        }
        pageResult.setItems(fillQuanZiVo(records));
        return pageResult;
    }

    /**
     * 抽取出来用于填充推荐好友动态信息的方法
     *
     * @param records
     * @return
     */
    private List<QuanZiVo> fillQuanZiVo(List<Publish> records) {
        List<QuanZiVo> quanZiVoList = new ArrayList<>();
        for (Publish record : records) {
            QuanZiVo quanZiVo = new QuanZiVo();
            quanZiVo.setId(record.getId().toHexString());
            quanZiVo.setTextContent(record.getText());
            quanZiVo.setImageContent(record.getMedias().toArray(new String[]{}));
            quanZiVo.setUserId(record.getUserId());
            quanZiVo.setCreateDate(RelativeDateFormat.format(new Date(record.getCreated())));

            quanZiVoList.add(quanZiVo);
        }
        //查询用户的具体信息
        List<Object> userIds = CollUtil.getFieldValues(records, "userId");
        List<UserInfo> userInfoList = userInfoService.findUserInfoByUserIds(userIds);
        for (QuanZiVo quanZiVo : quanZiVoList) {
            //找到对应的用户信息
            for (UserInfo userInfo : userInfoList) {
                if (userInfo.getUserId().longValue() == quanZiVo.getUserId().longValue()) {
                    fillQuanZiVoByUserInfo(userInfo, quanZiVo);
                    break;
                }
            }
        }
        return quanZiVoList;
    }

    /**
     * 点赞的方法
     *
     * @param publishId
     * @return
     */
    public Long likeComment(String publishId) {
        //从本地线程获取user对象
        User user = UserThreadLocal.get();
        //点赞
        Boolean result = momentsApi.likeComment(user.getId(), publishId);
        //结果为true说明点赞成功
        if (result) {
            //从mongodb中查询点赞数个数
            return momentsApi.findLikeCount(publishId);
        }
        //返回false点赞失败返回null
        return null;
    }

    /**
     * 取消点赞的方法
     *
     * @param publishId
     * @return
     */
    public Long disLikeComment(String publishId) {
        //从本地线程获取user对象
        User user = UserThreadLocal.get();
        //取消点赞
        Boolean result = momentsApi.disLikeComment(user.getId(), publishId);
        //如果结果为true说明取消点赞成功
        if (result) {
            //从mongodb中查询点赞数个数
            return momentsApi.findLikeCount(publishId);
        }
        //返回false取消点赞失败返回null
        return null;
    }

    /**
     * 点击喜欢的方法
     *
     * @param publishId
     * @return
     */
    public Long loveComment(String publishId) {
        //从本地线程中获取user对象
        User user = UserThreadLocal.get();
        //点击喜欢
        Boolean result = momentsApi.loveComment(user.getId(), publishId);
        //如果返回true则喜欢成功
        if (result) {
            //从mongodb中获取喜欢数量
            return momentsApi.findLoveCount(publishId);
        }
        //点赞失败返回null
        return null;
    }

    /**
     * 取消喜欢
     *
     * @param publishId
     * @return
     */
    public Long unLoveComment(String publishId) {
        //从本地线程获取user对象
        User user = UserThreadLocal.get();
        //取消喜欢
        Boolean result = momentsApi.unLoveComment(user.getId(), publishId);
        if (result) {
            return momentsApi.findLoveCount(publishId);
        }
        return null;
    }

    /**
     * 查询单条动态的方法
     *
     * @param publishId
     * @return
     */
    public QuanZiVo findSinglePublish(String publishId) {
        //通过动态ID获取动态信息
        Publish publish = momentsApi.findPublishById(publishId);
        if (null == publish) {
            return null;
        }
        //使用工具类将publish转成集合对象,调用填充QuanZiVo的方法获取到的是集合,取第一条数据并返回
        return fillQuanZiVo(Arrays.asList(publish)).get(0);
    }

    /**
     * 查询评论列表
     *
     * @param publishId 动态的ID
     * @param page
     * @param pageSize
     * @return
     */
    public PageResult findCommentList(String publishId, Integer page, Integer pageSize) {
        //创建一个pageResult对象
        PageResult pageResult = new PageResult();
        pageResult.setPage(page);
        pageResult.setPagesize(pageSize);

        //从本地线程中获取用户信息
        User user = UserThreadLocal.get();

        PageInfo<Comment> pageInfo = momentsApi.findCommentList(publishId, page, pageSize);
        List<Comment> records = pageInfo.getRecords();
        if (CollUtil.isEmpty(records)) {
            return pageResult;
        }
        //从数据库中获取用户个人信息
        List<Object> userIds = CollUtil.getFieldValues(records, "userId");
        List<UserInfo> userInfoList = userInfoService.findUserInfoByUserIds(userIds);

        List<CommentVo> commentVoList = new ArrayList<>();

        for (Comment comment : records) {
            CommentVo commentVo = new CommentVo();
            commentVo.setId(comment.getId().toHexString());//评论的ID
            commentVo.setContent(comment.getContent());
            commentVo.setCreateDate(DateUtil.format(new Date(comment.getCreated()), "HH:mm"));
            commentVo.setLikeCount(Convert.toInt(momentsApi.findLikeCount(commentVo.getId())));//commentVo.getId()是评论的ID
            commentVo.setHasLiked(momentsApi.findLikeRecord(user.getId(), commentVo.getId()) ? 1 : 0);//是否点赞

            for (UserInfo userInfo : userInfoList) {
                if (ObjectUtil.equals(comment.getUserId(), userInfo.getUserId())) {
                    commentVo.setNickname(userInfo.getNickName());
                    commentVo.setAvatar(userInfo.getLogo());
                    break;
                }
            }
            commentVoList.add(commentVo);
        }
        pageResult.setItems(commentVoList);
        return pageResult;
    }

    /**
     * 发表评论
     *
     * @param publishId
     * @param content
     * @return
     */
    public Boolean sendComment(String publishId, String content) {
        //获取本地线程中的用户信息
        User user = UserThreadLocal.get();

        //判断该用户是否在冻结中
        String redisKey = getFreezeUserRedisKeyPrefix(Convert.toInt(user.getId()));
        String data = redisTemplate.opsForValue().get(redisKey);
        if (ObjectUtil.isNotEmpty(data)) {
            JSONObject jsonObject = JSONUtil.parseObj(data);
            Object freezingRange = jsonObject.get("freezingRange");
            if (ObjectUtil.equal(freezingRange, 2)) {
                //表示用户是登录被封禁中
                return false;
            }
        }
        return momentsApi.sendComment(user.getId(), publishId, content);
    }

    /**
     * 查看用户动态
     *
     * @param userId
     * @param page
     * @param pageSize
     * @return
     */
    public PageResult findOneUserPublish(Long userId, Integer page, Integer pageSize) {
        PageResult pageResult = new PageResult();
        pageResult.setPage(page);
        pageResult.setPagesize(pageSize);
        PageInfo<Publish> publishList = momentsApi.findOneUserPublish(userId, page, pageSize);
        if (ObjectUtil.isEmpty(publishList.getRecords())) {
            return pageResult;
        }
        pageResult.setItems(fillQuanZiVo(publishList.getRecords()));
        return pageResult;
    }

    /**
     * 谁看过我
     *
     * @return
     */
    public List<VisitorsVo> findVisitors() {
        User user = UserThreadLocal.get();
        List<Visitors> visitorsList = visitorsApi.findVisitorsList(user.getId());
        if (CollUtil.isEmpty(visitorsList)) {
            return Collections.emptyList();
        }
        List<Object> userId = CollUtil.getFieldValues(visitorsList, "visitorUserId");

        List<UserInfo> userInfoList = userInfoService.findUserInfoByUserIds(userId);
        List<VisitorsVo> visitorsVoList = new ArrayList<>();

        for (UserInfo userInfo : userInfoList) {
            for (Visitors visitors : visitorsList) {
                if (ObjectUtil.equals(userInfo.getUserId(), visitors.getVisitorUserId())) {
                    VisitorsVo visitorsVo = new VisitorsVo();
                    visitorsVo.setId(userInfo.getUserId());
                    visitorsVo.setAvatar(userInfo.getLogo());
                    visitorsVo.setNickname(userInfo.getNickName());
                    visitorsVo.setTags(userInfo.getTags().split(","));
                    visitorsVo.setGender(userInfo.getSex().name().toLowerCase());
                    visitorsVo.setFateValue(visitors.getScore().intValue());
                    visitorsVoList.add(visitorsVo);
                    break;
                }
            }
        }
        return visitorsVoList;
    }

    private String getFreezeUserRedisKeyPrefix(Integer uid) {
        return FREEZE_USER_REDIS_KEY_PREFIX + uid;
    }
}
